import 'package:built_collection/built_collection.dart';
import 'package:equatable/equatable.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/app_navigator_transition_info.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/page_models/app_navigator_page_model.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/page_models/home_page_model/home_page_model.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/page_models/signing_in_page_model.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/user.dart';
import 'package:learning_content_admin_pannel.core/core/domain/utils/uuid_generator.dart';

part 'result.dart';

abstract class ApplyPageGuard {
  PageGuardApplicationResult call({
    required BuiltList<AppNavigatorPageModel> pageModels,
    required BuiltMap<AppNavigatorPageModel, AppNavigatorTransitionInfo> pageModelToTransitionInfo,
    required User? user,
  });
}

class ApplyPageGuardImpl implements ApplyPageGuard {
  const ApplyPageGuardImpl();

  @override
  PageGuardApplicationResult call({
    required BuiltList<AppNavigatorPageModel> pageModels,
    required BuiltMap<AppNavigatorPageModel, AppNavigatorTransitionInfo> pageModelToTransitionInfo,
    required User? user,
  }) {
    final updatedPageModelToTransitionInfo = pageModelToTransitionInfo.toMap();

    if (user == null) {
      var i = 0;

      while (i < pageModels.length &&
          (pageModels[i].permittedWithoutAuthorization ||
              pageModelToTransitionInfo[pageModels[i]] is RemovalNavigatorTransitionInfo)) {
        i++;
      }

      SigningInPageModel? signingInPageModel;

      if (i < pageModels.length) {
        signingInPageModel = SigningInPageModel(
          targetPageModel: pageModels[i].copyWith(
            id: () => UuidGenerator().generateUuid(),
          ),
        );
      }

      while (i < pageModels.length) {
        final pageModel = pageModels[i];

        if (updatedPageModelToTransitionInfo[pageModel] is! RemovalNavigatorTransitionInfo) {
          updatedPageModelToTransitionInfo[pageModel] = const RemovalNavigatorTransitionInfo(
            hasAnimation: false,
          );
        }

        i++;
      }

      var updatedPageModels = pageModels;

      if (signingInPageModel != null) {
        updatedPageModels = updatedPageModels.rebuild((pageModels) {
          pageModels.add(signingInPageModel!);
        });

        updatedPageModelToTransitionInfo[signingInPageModel] =
            const AdditionNavigatorTransitionInfo(
          hasAnimation: false,
        );
      }

      final result = PageGuardApplicationResult(
        pageModels: updatedPageModels,
        pageModelToTransitionInfo: updatedPageModelToTransitionInfo.build(),
      );

      return result;
    }

    var i = 0;
    var currentEffectivePermittedPageModelCount = 0;

    while (i < pageModels.length) {
      final pageModel = pageModels[i];

      if (pageModel.permittedWithAuthorization &&
          pageModelToTransitionInfo[pageModel] is! RemovalNavigatorTransitionInfo) {
        currentEffectivePermittedPageModelCount++;
      }

      if (!pageModel.permittedWithAuthorization &&
          pageModelToTransitionInfo[pageModel] is! RemovalNavigatorTransitionInfo) {
        updatedPageModelToTransitionInfo[pageModel] = const RemovalNavigatorTransitionInfo(
          hasAnimation: false,
        );
      }

      i++;
    }

    final shouldAddHomePage = currentEffectivePermittedPageModelCount == 0;

    var updatedPageModels = pageModels;

    if (shouldAddHomePage) {
      final pageModel = HomePageModel(
        fragmentModel: const WordFragmentModel(),
      );

      updatedPageModels = updatedPageModels.rebuild((pageModels) {
        pageModels.add(pageModel);
      });

      updatedPageModelToTransitionInfo[pageModel] = const AdditionNavigatorTransitionInfo(
        hasAnimation: false,
      );
    }

    final result = PageGuardApplicationResult(
      pageModels: updatedPageModels,
      pageModelToTransitionInfo: updatedPageModelToTransitionInfo.build(),
    );

    return result;
  }
}
